;--------------------------------------------------------------------------------------------------
;Micro Operation System Project Copyright 2012
;Author : Ilya Churaev
;Started : 20 Apr 2012		Updated : 18 Nov 2012
;File Name : process.asm	Purpose : low function for process
;--------------------------------------------------------------------------------------------------

; Это достаточно хитрый способ чтения указателя текущей инструкции. Когда вызывается функция read_eip, 
; адрес текущего местоположения инструкции помещается в стек. Обычно для того, чтобы вернуться из 
; функции, мы используем команду "ret". Эта команда извлекает значение адреса из стека и переходит по
; этому адресу. Однако здесь мы сами выталкиваем значение адреса из стека в регистр EAX (вспомните, что 
; согласно договоренности о вызове __cdecl регистр EAX является регистром 'значения возврата'), а 
; затем переходим по этому адресу.
[GLOBAL read_eip]
read_eip:
	pop eax						; Get the return address
	jmp eax						; Return. Can't use RET because return
								; address popped off the stack. 

[GLOBAL copy_page_physical]
copy_page_physical:
	push ebx					; Согласно to __cdecl необходимо сохранить содержимое ebx
	pushf						; Помещаю в стек EFLAGS с тем, чтобы мог оттуда их забрать и
								; заново включить прерывания.
	cli							; Отключаю прерывания
	; Перед тем, как отключить страничную организацию памяти загружаю:
	mov ebx, [esp+12]			; адрес, откуда делается копирование
	mov ecx, [esp+16]			; фдрес, куда выполняется копирование
  
	mov edx, cr0				; Беру регистр управления
	and edx, 0x7fffffff			; и
	mov cr0, edx				; Отключаю страничную организацию памяти
  
	mov edx, 1024				; 1024*4 байтов = копируется 4096 байтов
  
.loop:
	mov eax, [ebx]				; Беру слово из адреса источника
	mov [ecx], eax				; Запоминаю его по адресу приемника
	add ebx, 4					; Адрес источника += sizeof (word)
	add ecx, 4					; Адрес приемника += sizeof (word)
	dec edx						; Осталось скопировать на одно слово меньше
	jnz .loop             
  
	mov edx, cr0				; Снова беру регистр управления
	or  edx, 0x80000000			; и
	mov cr0, edx				; включаю страничное управление памятью
  
	popf						; востанавливаю EFLAGS
	pop ebx						; Помещаю исходное состояние в EBX
    ret
